package com.kpmg.datalake.common.utils.signutils;

import com.kpmg.datalake.common.utils.EncrypUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;

/**
 * ClassName: SignUtil
 * @Description: 验签工具
 * @author yechangpeng
 * @date 2017年5月20日
 */
public class SignUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(SignUtil.class);
	private String signType = "SHA256";
	private String charset = "UTF-8";
	/**
	 * @Description: 获取签名
	 * @param @return   
	 * @return String  
	 * @throws
	 * @author yechangpeng
	 * @date 2017年5月20日
	 */
	private String getSign(SortedMap<String, String> packageParam){
		StringBuilder sb = new StringBuilder();
		for (Entry<String, String> entry : packageParam.entrySet()) {
			String k = entry.getKey();
			String v = entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k)) {
				sb.append(v);
			}
		}
		String sign = null;
		switch (signType) {
			case "MD5":
				sign = Md5Util.md5Encode(sb.toString(), charset);
				break;
			case "SHA256":
				sign = EncrypUtil.encryptSha256(sb.toString(), charset);
				break;
			default:
				sign = Md5Util.md5Encode(sb.toString(), charset);
				break;
		}
		return sign;
	}
	/**
	 * @Description: 验签
	 * @param @param packageParam:需要加入验签的map;locaSign：接收到的签名
	 * @param @return   
	 * @return boolean  
	 * @throws
	 * @author yechangpeng
	 * @date 2017年5月20日
	 */
	public boolean checkSign(SortedMap<String, String> packageParam,String locaSign){
		String sign = getSign(packageParam);
		return (sign!=null&&sign.equals(locaSign));
	}
	
	public boolean checkSign(HttpServletRequest request,String privateKey){
		SortedMap<String, String> packageParam = new TreeMap<>();
		Map<String, String[]> parameterMap = request.getParameterMap();  
	    for (Entry<String, String[]> item : parameterMap.entrySet()) {
	    	String key = item.getKey();
	    	String value = request.getParameter(key);
	    	packageParam.put(key, value);
		}
	    packageParam.put("key", privateKey);
		String locaSign = packageParam.get("sign");
		String sign = getSign(packageParam);
		return (sign!=null&&sign.equals(locaSign));
	}
	/**
	 * @Description: 获取时间戳//2015-01-01 00:00:00 距今秒数
	 * @param @return   
	 * @return long  
	 * @throws
	 * @author yechangpeng
	 * @date 2017年5月20日
	 */
	private long getTimestamp(){
		Calendar c=Calendar.getInstance();
		  try {
		   c.setTime(new SimpleDateFormat("yyyy-mm-dd").parse("2015-01-01"));
		  } catch (ParseException e) {
			  logger.error(e.getMessage());
		  }
		return (System.currentTimeMillis()-c.getTimeInMillis())/1000;
	}
	/**
	 * @Description: 验证时间戳是否有效
	 * @param @param timestamp
	 * @param @param effectiveTime
	 * @param @return   
	 * @return boolean  
	 * @throws
	 * @author yechangpeng
	 * @date 2017年5月20日
	 */
	public boolean checkTimestamp(String timestamp,Long effectiveTime){
		long timeOld = Long.parseLong(timestamp);
		long timeNow = getTimestamp();
		return (timeNow-timeOld<effectiveTime);
	}
	
	/**
	 * @Description: 获取1000以内随机数
	 * @param @return   
	 * @return String  
	 * @throws
	 * @author yechangpeng
	 * @date 2017年5月26日
	 */
	private String getNonceStr(){
		Random random = new Random();
		return String.valueOf(random.nextInt(1000));
	}
	
	/**  
	 * @Title:       getDataMap  
	 * @Description: 获取带签名的参数
	 * @param packageParam 待加签名的map
	 * @param auth         授权码
	 * @return
	 * @author       changpengye 
	 * @version      V1.0
	 * @date         2018年6月7日 下午5:37:50
	 * @modifier     
	 * @reason       
	 */ 
	public Map<String,Object> getDataMap(SortedMap<String, String> packageParam,String privateKey,String auth){
		Map<String,Object> dataMap = new HashMap<>();
		packageParam.put("nonceStr",getNonceStr() );
		packageParam.put("timestamp", String.valueOf(getTimestamp()));
		packageParam.put("auth", auth);
		
		for (Entry<String, String> entry : packageParam.entrySet()) {
			String k = entry.getKey();
			String v = entry.getValue();
			if (null != v && !"".equals(v) && !"sign".equals(k)) {
				dataMap.put(k, v);
			}
		}		
		packageParam.put("key", privateKey);
		String sign = getSign(packageParam);
		dataMap.put("sign", sign);
		return dataMap;
	}
}
